package com.jlpay.open.jlpay.sdk.java.utils.json;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.TimeZone;

/**
 * JSON工具类
 * 
 * @author qihuaiyuan
 * @author zhaomeixia
 * @since 3.0.0
 */
public final class JsonUtils {

    private JsonUtils() {
        throw new IllegalStateException("Utility class");
    }

    private static ObjectMapper getMapper() {
        return ObjectMapperHolder.INSTANCE;
    }

    public static String toString(Object value) {
        if (value == null) {
            return null;
        }
        try {
            return getMapper().writeValueAsString(value);
        } catch (JsonProcessingException e) {
            throw new IllegalArgumentException (e);
        }
    }

    public static <T> T parseObject(String jsonStr, Class<T> type) {
        if (jsonStr == null) {
            return null;
        }
        try {
            return getMapper().readValue(jsonStr, type);
        } catch (JsonProcessingException e) {
            throw new IllegalArgumentException (e);
        }
    }

    public static <T> List<T> parseList(String jsonStr, Class<T> type) {
        JavaType javaType = getMapper().getTypeFactory().constructCollectionType(List.class, type);
        try {
            return getMapper().readValue(jsonStr, javaType);
        } catch (JsonProcessingException e) {
            throw new IllegalArgumentException (e);
        }
    }
    public static ObjectNode createObjectNode() {
        return getMapper().createObjectNode();
    }



    private static class ObjectMapperHolder {
        private static final ObjectMapper INSTANCE = JsonMapper.builder()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
                .configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true)
                .configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE, true)
                .enable(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)
                .serializationInclusion(JsonInclude.Include.NON_NULL)
                .propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
                .defaultDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
                .defaultTimeZone(TimeZone.getTimeZone("GMT+8"))
                .build();
    }
}
